/*
 * Created by SharpDevelop.
 * User: phtrung
 * Date: 8/6/2008
 * Time: 6:16 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using System.Web.Security;

namespace popLib
{
	/// <summary>
	/// Description of stringCls.
	/// </summary>
	public class StringLib
	{
		//get arraylist of all string, that apdapt with this condition (from A to B)
		public static ArrayList getListGroupString(string src, string from, string to){
			int startIndex = 0;
			ArrayList result = new ArrayList();
			
			while( startIndex >=0 ){
				string imageStr = subString( src, from, to, startIndex);
				
				if(imageStr.Trim().Length == 0) break;
				
				startIndex = src.IndexOf( imageStr, startIndex ) + 1;
				
				result.Add(imageStr);
			}
			return result;
		}
		
		
		
		//get arraylist of all string, that apdapt with this condition (from A to B, without A,B)
		public static ArrayList getListGroupStringInside(string src, string from, string to){
			int startIndex = 0;
			ArrayList result = new ArrayList();
			
			while( startIndex >=0 ){
				string imageStr = subStringBetween( src, from, to, startIndex);
				
				if(imageStr.Trim().Length == 0) break;
				
				startIndex = src.IndexOf( imageStr, startIndex ) + 1;
				
				result.Add(imageStr);
			}
			return result;
		}
		
		//get string from string A, to string B but dont have A and B
		//12345678 --> get from 23 to 78 --> 456
		public static string subStringBetween(string src, string from, string to, int fromIndex){
			return subString(src,from,to,fromIndex).Replace(from,"").Replace(to,"");
		}
		//get string from string A, to string B
		//12345678 --> get from 23 to 78 --> 2345678
		public static string subString(string src, string from, string to, int fromIndex){
			string result = "";
			
			if(src.IndexOf(from,fromIndex) >= 0 ){
				int startIndex = src.IndexOf(from,fromIndex);
				int endIndex   = src.IndexOf(to, startIndex + from.Length);
				int length	   = endIndex - startIndex + to.Length;
				if(startIndex >= 0 && length > 0)
					result = src.Substring( startIndex, length);
			}
			return result;
		}
		
		//matchAny: str1;str2;str3
		public static int indexOfAny(string str, string matchAny){
			for( int i = 0; i < matchAny.Length; i++ ){
				string oneChar = matchAny.Substring(i,1);
				if( str.IndexOf(oneChar) >= 0 )
					return str.IndexOf(oneChar);
			}
			return -1;
		}
		
		//matchAny: str1;str2;str3
		public static int indexOfAny(string name, string[] matchAny){
			foreach(string item in matchAny)
				if(name.IndexOf(item)>=0) return name.IndexOf(item);
			return -1;
		}
		
		public static string decodeSpecialChar(string content){
			return content.Replace("\\r","\r").Replace("\\n","\n").Replace("\\t","\t");
		}
		
		public static string encodeSpecialChar(string content){
			return content.Replace("\r","\\r").Replace("\n","\\n").Replace("\t","\\t");
		}
		
		
		public static string capFirstLetter(string str){
			string firstLetter = str.Substring(0,1);
			return firstLetter.ToUpper() + str.Substring(1);
		}
		
		public static string lowFirstLetter(string str){
			string firstLetter = str.Substring(0,1);
			return firstLetter.ToLower() + str.Substring(1);
		}
		
		/// <summary>
		/// Split input string to string array by split input string depend on one of the list
		/// of passed string[] separaters
		/// </summary>
		/// <param name="str"></param>
		/// <param name="separaters"></param>
		/// <returns></returns>
		public static string[] splitByAny( string str, string[] separaters ){
			string[] items = str.Replace( separaters[0], (char)(128)+"" ).Split( (char)(128) );
			foreach( string separater in separaters )
				if( str.IndexOf(separater) >= 0 )
				items = str.Replace( separater, (char)(128)+"" ).Split( (char)(128) );
			
			return items;
		}
		
		/// <summary>
		/// Split input string to string[] by split using each letter of the separaters
		/// Note: use for split with separator is single character only.
		/// </summary>
		/// <param name="str"></param>
		/// <param name="separaters"></param>
		/// <returns></returns>
		public static string[] splitByAny( string str, string separaters ){
			string[] items = str.Replace( separaters.Substring(0,1), (char)(128)+"" ).Split( (char)(128) );
			for( int i = 0; i < separaters.Length; i++ ){
				string separater = separaters.Substring(i,1);
				if( str.IndexOf(separater) >= 0 )
					items = str.Replace( separater, (char)(128)+"" ).Split( (char)(128) );
			}
			
			return items;
		}
		
		/// <summary>
		/// Convert String to hashtable with specific rule and splitter string		
		/// </summary>
		/// <param name="options">key=value&key=value or key:value\r\nkey:value</param>
		/// <param name="optionSplitterChar">Splitter character between each option</param>
		/// <param name="valueSpliterChar">Splitter character between key and value (for each option)</param>
		/// <returns></returns>
		public static Hashtable parseOption(string options, char optionSplitterChar, char valueSpliterChar ){
			Hashtable result = new Hashtable();
			
			if(options != null){								
				string[] optionArr = splitByAny(options, optionSplitterChar.ToString() );
				string[] content;
				
				foreach( string option in optionArr ){
					if( !option.Contains(valueSpliterChar.ToString()) ) continue;
					
					content = StringLib.Replace1time( option, valueSpliterChar.ToString(), (char)(127) + "" ).Split( (char)(127) );
					
					if(content.Length == 2){
						result.Add( content[0].Trim(), content[1].Trim() );
					}
				}
			}
			
			return result;
		}
		
		/// <summary>
		/// Convert String to hashtable by rule key=value&key=value
		/// </summary>
		/// <param name="options">key=value&key=value</param>
		/// <returns></returns>
		public static Hashtable parseOption(string options ){
			return parseOption( options, '&', '=');
		}
		
		/// <summary>
		/// Convert hashtable to string specific rule and splitter string
		/// </summary>
		/// <param name="options">hashtable</param>
		/// <param name="optionSplitterChar">& or \r\n or something else</param>
		/// <param name="valueSpliterChar">= or : or anything else</param>
		/// <returns></returns>
		public static string deParseOption( Hashtable options, char optionSplitterChar, char valueSpliterChar  ){
			string result = "";
			foreach( string key in options.Keys ){
				result += string.Format( "{0}{2}{1}{3}", key, options[key], valueSpliterChar.ToString(), optionSplitterChar.ToString() );
			}
			
			if( result.EndsWith(optionSplitterChar.ToString()) )
				result = (result+optionSplitterChar).Replace( optionSplitterChar + "" + optionSplitterChar,"");
			return result;
		}
		
		/// <summary>
		/// Convert hashtable to String by rule key=value&key=value
		/// </summary>
		/// <param name="options">key=value&key=value</param>
		/// <returns></returns>
		public static string deParseOption( Hashtable options ){
			return deParseOption( options, '&', '=' );
		}
		
		//Return space left of a string
		public static  string spaceleft(string currentStr,int totallength)
		{
			return spaceleft( currentStr, totallength, " " );
		}
		
		//Return character left of a string
		public static  string spaceleft(string currentStr, int totalLength, string newChar)
		{
			string spacereturn = "";
			if(currentStr.Length<totalLength)
			{
				for(int i=0;i<totalLength - currentStr.Length;i++)
					spacereturn += newChar;
			}
			return spacereturn;
		}
		
		public static string spaceLeftInclude( object currentStr,int totalLength, string newChar ){
			return spaceleft( currentStr+"", totalLength, newChar ) + currentStr;
		}
		public static string spaceLeftInclude( object currentStr,int totalLength ){
			return spaceleft( currentStr+"", totalLength, " " ) + currentStr;
		}
		
		//Return only char that in filter list
		public static string filterStr(string var,string filstr)
		{
			string rs = "";
			for(int i=0;i<var.Length;i++)
				if(filstr.IndexOf(var.Substring(i,1)) >= 0)
				rs += var.Substring(i,1);
			return rs;
		}
		
		
		
		//Return string that is replace filstr 1 time;
		public static string Replace1time(string val,string oldstr,string newstr)
		{
			if(val.IndexOf(oldstr) >= 0)
			{
				string buf = val.Substring(0,val.IndexOf(oldstr));
				string buf1= val.Substring( val.IndexOf(oldstr)+oldstr.Length , val.Length - (val.IndexOf(oldstr)+oldstr.Length));
				return buf+newstr+buf1;
			}
			else return val;
		}
		
		public static string encodeTo64(string toEncode)
		{
			byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
			string returnValue     = System.Convert.ToBase64String(toEncodeAsBytes);
			return returnValue;
		}
		
		public static string encodeTo64(string toEncode, string char_key)
		{
			try{
				string lastEncode = "";
				int charIndex = -1;
				int keyLength = char_key.Length;
				
				//encode to 64base
				char_key = encodeTo64(char_key);
				toEncode = encodeTo64(toEncode);
				
				for(int i=0;i<toEncode.Length;i++){
					lastEncode+= toEncode.Substring(i,1);
					
					charIndex++;
					if(charIndex >= char_key.Length) charIndex = 0;
					lastEncode+= char_key.Substring(charIndex,1);
				}
				lastEncode = keyLength+"[[=]]"+lastEncode;
				return encodeTo64(lastEncode);
			}catch(Exception ex){ex.ToString();}
			return "#Error";
		}
		
		public static string decodeFrom64(string encodedData)
		{
			byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
			string returnValue = System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
			return returnValue;
		}
		public static string decodeFrom64(string encodedData, string char_key)
		{
			try{
				string decoded = decodeFrom64( encodedData );
				if( decoded.IndexOf("[[=]]") == -1 ) return "???#";
				int keyLength = NumberLib.getInt( splitByAny( decoded, new string[]{"[[=]]"} )[0] );
				decoded = splitByAny( decoded, new string[]{"[[=]]"} )[1];
				if( char_key.Length != keyLength ) return "???L";
				
				char_key = encodeTo64(char_key);
				string result = "";
				string compareKey = "";
				for( int i=0;i<decoded.Length;i+=2){
					result 		+= decoded.Substring(i,1);
					compareKey 	+= decoded.Substring(i+1,1);
				}
				
				string buildKey = "";
				int charIndex = -1;
				for(int i=0;i<compareKey.Length;i++){
					charIndex++;
					if(charIndex >= char_key.Length) charIndex = 0;
					buildKey+= char_key.Substring(charIndex,1);
				}
				
				if( compareKey == buildKey )
					return decodeFrom64(result);
				else return "???";
			}catch(Exception ex){ex.ToString();}
			return "#Error";
		}
		
		public static bool isValid(string str){
			if( str != null && str.Trim().Length > 0 ) return true;
			return false;
		}
		
		
		/// <summary>
		/// Encript string with key, include md5 (optional)
		/// Support decrypt		
		/// </summary>
		/// <param name="toEncrypt">String to encript</param>
		/// <param name="key">Key to encript your string, also known as password</param>
		/// <param name="useHashing">true: to use md5 to encode</param>
		/// <returns>Encoded string</returns>
		public static string encrypt(string toEncrypt, string key, bool useHashing)
		{
			byte[] keyArray;
			byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

			if (useHashing)
			{
				MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
				keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
			}
			else
				keyArray = UTF8Encoding.UTF8.GetBytes(key);

			TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
			tdes.Key = keyArray;
			tdes.Mode = CipherMode.ECB;
			tdes.Padding = PaddingMode.PKCS7;

			ICryptoTransform cTransform = tdes.CreateEncryptor();
			byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

			return Convert.ToBase64String(resultArray, 0, resultArray.Length);
		}
		
		/// <summary>
		/// Decript encoded string with key, include md5 (optional)
		/// </summary>
		/// <param name="toDecrypt">String to decript</param>
		/// <param name="key">Key to decript your string, also known as password</param>
		/// <param name="useHashing">True: to use md5 to encode</param>
		/// <returns>Decoded string</returns>
		public static string decrypt(string toDecrypt, string key, bool useHashing)
		{
			byte[] keyArray;
			byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

			if (useHashing)
			{
				MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
				keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
			}
			else
				keyArray = UTF8Encoding.UTF8.GetBytes(key);

			TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
			tdes.Key = keyArray;
			tdes.Mode = CipherMode.ECB;
			tdes.Padding = PaddingMode.PKCS7;

			ICryptoTransform cTransform = tdes.CreateDecryptor();
			byte[] resultArray= cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

			return UTF8Encoding.UTF8.GetString(resultArray);
		}
		
		
		
		/// <summary>
		/// Encrypt password in MD5 or SHA1
		/// </summary>
		/// <param name="password">string password to encode</param>
		/// <param name="format">Format could be MD5 or SHA1</param>
		/// <returns>Ecrypted string</returns>
		public static string encryptPassword(string password, EncryptPasswordFormat format)
		{			
			return FormsAuthentication.HashPasswordForStoringInConfigFile(password, format.ToString());
		}
		
		
	}
	
	public enum EncryptPasswordFormat{ MD5, SHA1 }
}
